﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace Slaks.Graphs.Analysis.ClusteringMeasures
{
    public class MutualInformation : ClusteringMeasureBase
    {
        public override object evaluate(GraphList[] clusters, Slaks.Graphs.Category.CategoriesFile categoriesFile)
        {
            Document2CategoryMap document2categoryMap = categoriesFile.DocumentToCategoryMap;
            IList categoryList = categoriesFile.categoriesList;
            int numberOfGraphs = CountGraphs(clusters);

            double mutualInformation = 0.0;
            int numberOfAlgorithmClusters = clusters.Length;
            int numberOfGroundTruthClusters = categoryList == null ? clusters.Length : categoryList.Count;
            int logBase = numberOfAlgorithmClusters * numberOfGroundTruthClusters;

            double tempPart;

            int numberOfItems;

            int innerFirst = 0, innerSecond = 0;

            //AddCentroidsToList(clusters);

            for (int l = 0; l < numberOfAlgorithmClusters; l++)
            {
                for (int h = 0; h < numberOfGroundTruthClusters; h++)
                {
                    numberOfItems = IRAnalysis.GetNumberOfClustersIJ(clusters, categoryList, document2categoryMap, l, h);

                    tempPart = numberOfItems * numberOfGraphs;

                    innerFirst = innerSecond = 0;
                    for (int i = 0; i < numberOfAlgorithmClusters; i++)
                    {
                        innerFirst += IRAnalysis.GetNumberOfClustersIJ(clusters, categoryList, document2categoryMap, i, h);
                    }

                    for (int i = 0; i < numberOfGroundTruthClusters; i++)
                    {
                        innerSecond += IRAnalysis.GetNumberOfClustersIJ(clusters, categoryList, document2categoryMap, l, i);
                    }

                    if (tempPart != 0.0) tempPart /= (innerFirst * innerSecond);
                    if (tempPart != 0.0) tempPart = Math.Log(tempPart, logBase);

                    mutualInformation += numberOfItems * tempPart;
                }
            }

            if (mutualInformation != 0.0) mutualInformation /= numberOfGraphs;

            //RemoveCentroidsFromList(clusters);
            return mutualInformation;
        }

        public int CountGraphs( GraphList [] graphs)
        {
            int count = 0;
            foreach (GraphList cluster in graphs )
            {
                count += cluster.Count;
            }
            return count;
        }

        public override string getMeasureName()
        {
            return "MI";
        }
    }
}
